#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <cstring>
#include <filesystem>

// 使用1字节对齐确保结构体准确解析二进制数据
#pragma pack(push, 1)
struct RIFFHeader {
    char chunkID[4];        // 文件标识（"RIFF"）
    uint32_t chunkSize;     // 文件总大小-8字节
    char format[4];         // 格式类型（"WAVE"）
};

struct FMTSubchunk {
    char subchunk1ID[4];    // 格式标识（"fmt "）
    uint32_t subchunk1Size; // 格式块大小（16或更大）
    uint16_t audioFormat;   // 音频格式（1=PCM）
    uint16_t numChannels;   // 声道数（1-单声道，2-立体声）
    uint32_t sampleRate;    // 采样率（Hz）
    uint32_t byteRate;      // 字节率（每秒数据量）
    uint16_t blockAlign;    // 数据块对齐单位
    uint16_t bitsPerSample; // 每个采样的位数
};

struct DataHeader {
    char subchunk2ID[4];    // 数据块标识（"data"）
    uint32_t subchunk2Size; // 音频数据总字节数
};
#pragma pack(pop) // 恢复默认对齐方式

/**
 * 只支持16-bit音频
 */
class WAVProcessor {
public:
    // 构造函数：加载并解析WAV文件
    explicit WAVProcessor(const std::string& filename) {
        std::ifstream file(filename, std::ios::binary);
        if (!file) {
            throw std::runtime_error("Failed to open file");
        }

        // 读取RIFF文件头
        file.read(reinterpret_cast<char*>(&riff), sizeof(RIFFHeader));
        validateHeader();
        
        // 读取格式子块
        file.read(reinterpret_cast<char*>(&fmt), sizeof(FMTSubchunk));
        validateFormat();

        // 跳过可能存在的扩展信息
        if (fmt.subchunk1Size > 16) {
            file.seekg(fmt.subchunk1Size - 16, std::ios::cur);
        }

        // 读取数据块头
        file.read(reinterpret_cast<char*>(&dataHeader), sizeof(DataHeader));
        validateDataHeader();

        // 加载音频数据
        audioData.resize(dataHeader.subchunk2Size);
        file.read(reinterpret_cast<char*>(audioData.data()), dataHeader.subchunk2Size);
    }

    // 打印文件头信息
    void printHeaderInfo() const {
        printRiffHeader();
        printFmtSubchunk();
        printDataHeader();
    }

    // 分割立体声文件为左右声道
    void splitChannels(const std::string& leftFile, 
                      const std::string& rightFile) {
        if (fmt.numChannels != 2) {
            throw std::runtime_error("Input is not a stereo file");
        }
        if (fmt.bitsPerSample != 16) {
            throw std::runtime_error("Only 16-bit audio is supported");
        }

        // 分离音频数据
        auto [left, right] = processAudioData();

        // 写入单声道文件
        writeMonoFile(leftFile, left);
        writeMonoFile(rightFile, right);
    }

private:
    RIFFHeader riff{};         // RIFF文件头存储
    FMTSubchunk fmt{};         // 格式信息存储
    DataHeader dataHeader{};   // 数据块头存储
    std::vector<uint8_t> audioData; // 原始音频数据缓冲区

    // 验证RIFF头有效性
    void validateHeader() const {
        if (memcmp(riff.chunkID, "RIFF", 4) != 0 || memcmp(riff.format, "WAVE", 4) != 0) {
            throw std::runtime_error("Invalid WAV file");
        }
    }

    // 验证格式块有效性
    void validateFormat() const {
        if (memcmp(fmt.subchunk1ID, "fmt ", 4) != 0) {
            throw std::runtime_error("Invalid fmt subchunk");
        }
    }

    // 验证数据块有效性
    void validateDataHeader() const {
        if (memcmp(dataHeader.subchunk2ID, "data", 4) != 0) {
            throw std::runtime_error("Invalid data subchunk");
        }
    }

    // 辅助函数：以十六进制打印字节数据
    static void printBytes(const uint8_t* bytes, size_t len) {
        std::ios oldState(nullptr);
        oldState.copyfmt(std::cout);
        
        std::cout << std::hex << std::setfill('0');
        for (size_t i = 0; i < len; ++i) {
            std::cout << std::setw(2) << static_cast<int>(bytes[i]) << " ";
        }
        std::cout.copyfmt(oldState);
    }

    // 打印RIFF头详细信息
    void printRiffHeader() const {
        std::cout << "=== RIFF Header ===\n";
        std::cout << "ChunkID: ";
        printBytes(reinterpret_cast<const uint8_t*>(riff.chunkID), 4);
        std::cout << "\nDescription: RIFF identifier\n\n";

        std::cout << "ChunkSize: ";
        printBytes(reinterpret_cast<const uint8_t*>(&riff.chunkSize), 4);
        std::cout << "\nDescription: " << riff.chunkSize 
                 << " (File size - 8 bytes)\n\n";

        std::cout << "Format: ";
        printBytes(reinterpret_cast<const uint8_t*>(riff.format), 4);
        std::cout << "\nDescription: WAVE format\n\n";
    }

    // 打印格式块详细信息
    void printFmtSubchunk() const {
        std::cout << "=== Format Subchunk ===\n";
        std::cout << "Subchunk1ID: ";
        printBytes(reinterpret_cast<const uint8_t*>(fmt.subchunk1ID), 4);
        std::cout << "\nDescription: fmt identifier\n\n";

        std::cout << "Subchunk1Size: ";
        printBytes(reinterpret_cast<const uint8_t*>(&fmt.subchunk1Size), 4);
        std::cout << "\nDescription: " << fmt.subchunk1Size 
                 << " bytes\n\n";

        std::cout << "AudioFormat: ";
        printBytes(reinterpret_cast<const uint8_t*>(&fmt.audioFormat), 2);
        std::cout << "\nDescription: " << fmt.audioFormat 
                 << " (1 = PCM)\n\n";

        std::cout << "NumChannels: ";
        printBytes(reinterpret_cast<const uint8_t*>(&fmt.numChannels), 2);
        std::cout << "\nDescription: " << fmt.numChannels 
                 << " channels\n\n";

        std::cout << "SampleRate: ";
        printBytes(reinterpret_cast<const uint8_t*>(&fmt.sampleRate), 4);
        std::cout << "\nDescription: " << fmt.sampleRate 
                 << " Hz\n\n";

        std::cout << "ByteRate: ";
        printBytes(reinterpret_cast<const uint8_t*>(&fmt.byteRate), 4);
        std::cout << "\nDescription: " << fmt.byteRate 
                 << " bytes/sec\n\n";

        std::cout << "BlockAlign: ";
        printBytes(reinterpret_cast<const uint8_t*>(&fmt.blockAlign), 2);
        std::cout << "\nDescription: " << fmt.blockAlign 
                 << " bytes/block\n\n";

        std::cout << "BitsPerSample: ";
        printBytes(reinterpret_cast<const uint8_t*>(&fmt.bitsPerSample), 2);
        std::cout << "\nDescription: " << fmt.bitsPerSample 
                 << "-bit depth\n\n";
    }

    // 打印数据块头信息
    void printDataHeader() const {
        std::cout << "=== Data Subchunk ===\n";
        std::cout << "Subchunk2ID: ";
        printBytes(reinterpret_cast<const uint8_t*>(dataHeader.subchunk2ID), 4);
        std::cout << "\nDescription: data identifier\n\n";

        std::cout << "Subchunk2Size: ";
        printBytes(reinterpret_cast<const uint8_t*>(&dataHeader.subchunk2Size), 4);
        std::cout << "\nDescription: " << dataHeader.subchunk2Size 
                 << " bytes audio data\n\n";
    }

    // 分离音频数据到左右声道
    std::pair<std::vector<uint8_t>, std::vector<uint8_t>> processAudioData() const {
        const size_t frameSize = fmt.blockAlign;      // 每帧字节数
        const size_t totalFrames = audioData.size() / frameSize;

        std::vector<uint8_t> leftChannel;  // 左声道数据存储
        std::vector<uint8_t> rightChannel; // 右声道数据存储
        leftChannel.reserve(totalFrames * 2);
        rightChannel.reserve(totalFrames * 2);

        // 分离立体声数据
        for (size_t i = 0; i < totalFrames; ++i) {
            const size_t offset = i * frameSize;
            // 左声道（前2字节）
            leftChannel.insert(leftChannel.end(), 
                             audioData.begin() + offset, 
                             audioData.begin() + offset + 2);
            // 右声道（后2字节）
            rightChannel.insert(rightChannel.end(), 
                              audioData.begin() + offset + 2, 
                              audioData.begin() + offset + 4);
        }

        return {leftChannel, rightChannel};
    }

    // 写入单声道WAV文件
    void writeMonoFile(const std::string& filename, const std::vector<uint8_t>& data) const {
        std::ofstream out(filename, std::ios::binary);
        if (!out) {
            throw std::runtime_error("Failed to create output file");
        }

        // 创建新的文件头
        RIFFHeader newRiff = riff;
        FMTSubchunk newFmt = fmt;
        DataHeader newData = dataHeader;

        // 更新单声道参数
        newFmt.numChannels = 1;
        newFmt.byteRate = newFmt.sampleRate * newFmt.numChannels * newFmt.bitsPerSample / 8;
        newFmt.blockAlign = newFmt.numChannels * newFmt.bitsPerSample / 8;
        newData.subchunk2Size = static_cast<uint32_t>(data.size());
        newRiff.chunkSize = 36 + newData.subchunk2Size;

        // 写入头信息
        out.write(reinterpret_cast<const char*>(&newRiff), sizeof(RIFFHeader));
        out.write(reinterpret_cast<const char*>(&newFmt), sizeof(FMTSubchunk));
        out.write(reinterpret_cast<const char*>(&newData), sizeof(DataHeader));
        // 写入音频数据
        out.write(reinterpret_cast<const char*>(data.data()), data.size());
    }
};

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <input.wav>\n";
        return 1;
    }

    try {
        WAVProcessor processor(argv[1]);
        processor.printHeaderInfo();
        processor.splitChannels("left.wav", "right.wav");
        std::cout << "Processing completed\n";
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << "\n";
        return 1;
    }

    return 0;
}